package com.ccx.coachsite.http;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.json.JSONObject;

import com.ccx.coachsite.util.Log;
import com.ccx.coachsite.util.StringUtil;

/**
 * The HTTP request
 * 
 * @author caijj
 * 
 * @version 1.0
 */
public class HttpRequest {

	private static final String URL_SEPARATOR = "?";
	private static final String PARAMETER_SEPARATOR = "&";
	private static final String NAME_VALUE_SEPARATOR = "=";

	public static final String HTTP_METHOD_GET = "get";
	public static final String HTTP_METHOD_POST = "post";

	private String charSet;
	private String method;

	private HttpClient httpClient;
	private HttpRequestBase request;
	private List<NameValuePair> params;

	private Class<? extends BaseResp> clazz;

	
	public static BaseResp DoHttpRepuestPost(String Url, HashMap<String, Object> mpas)
	{
		HttpRequest request = new HttpRequest(BaseResp.class);
		BaseResp resp = new BaseResp();
		try {
			if(mpas != null)
			{
				Iterator<java.util.Map.Entry<String, Object>> ite= mpas.entrySet().iterator();
		        while(ite.hasNext()){
		        	java.util.Map.Entry<String, Object> entry = (java.util.Map.Entry<String, Object>) ite.next(); 
				    Object key = entry.getKey(); 
				    Object val = entry.getValue(); 
				    request.addParameter(key.toString(), val.toString());
				} 
			}
			
			resp = request.execute(Url);
			
			
			if (resp.isSuccess()) {
				String result = resp.getHttpResult();
				JSONObject jsonObject = new JSONObject(result);
				String status = jsonObject.getString("code");
				String desc = jsonObject.getString("desc");
				resp.setDesc(desc);
				resp.setErrorCode(status);
				if (status.equals("200")) {
					resp.setResponse(jsonObject.getString("response"));
					resp.setStatus(BaseResp.SUCCESS);
				} else {
					resp.setStatus(BaseResp.ERROR);
				}
			}
		} catch (Exception e) {
			resp.setStatus(BaseResp.ERROR);
			Log.e(e.getMessage(), e);
		} finally {
			request.release();
		}

		return resp;
	}
	
	public static BaseResp DoHttpRequest(String Url) {
		HttpRequest request = new HttpRequest(BaseResp.class);
		BaseResp resp = new BaseResp();
		try {
			resp = request.execute(Url);
			if (resp.isSuccess()) {
				String result = resp.getHttpResult();
				JSONObject jsonObject = new JSONObject(result);
				String status = jsonObject.getString("code");
				String desc = jsonObject.getString("desc");
				resp.setDesc(desc);
				resp.setErrorCode(status);
				if (status.equals("200")) {
					resp.setResponse(jsonObject.getString("response"));
					resp.setStatus(BaseResp.SUCCESS);
				} else {
					resp.setStatus(BaseResp.ERROR);
				}
			}
		} catch (Exception e) {
			resp.setStatus(BaseResp.ERROR);
			Log.e(e.getMessage(), e);
		} finally {
			request.release();
		}

		return resp;
	}

	public HttpRequest(Class<? extends BaseResp> clazz) {
		this(HTTP_METHOD_POST, clazz);
	}

	public HttpRequest(String method, Class<? extends BaseResp> clazz) {
		httpClient = new DefaultHttpClient();
		params = new ArrayList<NameValuePair>();
		charSet = HTTP.UTF_8;
		this.method = method;
		this.clazz = clazz;
	}

	public void setCharSet(String charSet) {
		this.charSet = charSet;
	}

	public void setHttpMethod(String method) {
		this.method = method;
	}

	/**
	 * add httprequest entiy
	 */
	public void addParameter(String key, String value) {
		params.add(new BasicNameValuePair(key, value));
	}

	public BaseResp execute(String url) {
		return execute(url, method);
	}
	
	public BaseResp execute(String url, String method, String file) {
		BaseResp resp = newInstance();

		if (resp == null) {
			resp = new BaseResp(BaseResp.ERROR);
			return resp;
		}
		
		if (this.method.equals(HTTP_METHOD_GET)) {
			url = prepareUrl(url);
			request = new HttpGet(url);
		} else {
			HttpPost post = new HttpPost(url);
			try {
				post.setEntity(new UrlEncodedFormEntity(params, charSet));
				
				if(!StringUtil.isEmpty(file))
				{
					File f = new File(file);
					FileEntity entity = new FileEntity(f, "binary/octet-stream");
					post.setEntity(entity);
				}
				
				request = post;
			} catch (UnsupportedEncodingException e) {
				Log.e(e.getMessage(), e);
				// e.printStackTrace();
				resp.setStatus(BaseResp.ERROR);
				return resp;
			}
		}

		String sResult = null;

		try {
			HttpResponse httpResp = execute(request);
			int statusCode = httpResp.getStatusLine().getStatusCode();

			if (statusCode == 200) {
				sResult = EntityUtils.toString(httpResp.getEntity(), charSet);
			} else {
				resp.setStatus(BaseResp.ERROR); // 访问不成功时，设置状态为ERROR
				HttpErrorDesc.setErrorDesc(statusCode, resp);
			}
		} catch (ParseException e) {
			Log.e("ParseException error message:" + e.getMessage(), e);
			resp.setStatus(BaseResp.ERROR);
			// e.printStackTrace();
		} catch (IOException e) { // 网络问题
			Log.e("IOException error message:" + e.getMessage(), e);
			resp.setStatus(BaseResp.ERROR);
			// e.printStackTrace();
		}
		resp.setResult(sResult);
		return resp;
	}

	public BaseResp execute(String url, String method) {
		return execute(url, method, "");
	}

	public HttpResponse execute(HttpRequestBase request)
			throws ClientProtocolException, IOException {
		this.request = request;
		return httpClient.execute(request);
	}

	private BaseResp newInstance() {
		try {
			return clazz.newInstance();
		} catch (IllegalAccessException e) {
			// e.printStackTrace();
			Log.e(e.getMessage(), e);
		} catch (InstantiationException e) {
			// e.printStackTrace();
			Log.e(e.getMessage(), e);
		}
		return null;
	}

	private String prepareUrl(String url) {
		if (params == null)
			params = new ArrayList<NameValuePair>();
		StringBuffer sb = new StringBuffer(url);
		for (int i = 0; i < params.size(); i++) {
			NameValuePair pair = params.get(i);
			if (url.contains(URL_SEPARATOR)) {
				parameterJoin(sb, PARAMETER_SEPARATOR, pair);
			} else {
				if (i == 0)
					parameterJoin(sb, URL_SEPARATOR, pair);
				else
					parameterJoin(sb, PARAMETER_SEPARATOR, pair);
			}
		}
		return url;
	}

	protected void parameterJoin(StringBuffer sb, String join,
			NameValuePair pair) {
		sb.append(join + pair.getName() + NAME_VALUE_SEPARATOR + pair.getName());
	}

	public void release() {
		if (request != null)
			request.abort();
	}
	
	private String encode(String value) throws Exception{  
        return URLEncoder.encode(value, "UTF-8");  
    }  
	
	/**
	 * 图片上传
	 * @param upUrl
	 * @param filePath
	 * @param fileName
	 * @return
	 */
	public String uploadFile(String upUrl, String filePath, String fileName) {
		String end = "\r\n";
		String twoHyphens = "--";
		String boundary = "*****";
		DataOutputStream ds = null;
		try {
			URL url = new URL(upUrl);
			HttpURLConnection con = (HttpURLConnection) url.openConnection();
			con.setDoInput(true);
			con.setDoOutput(true);
			con.setUseCaches(false);
			con.setRequestMethod("POST");
			con.setRequestProperty("Connection", "Keep-Alive");
			con.setRequestProperty("Charset", "UTF-8");
			
			InputStream fStream;
			boolean isSet = false;
			if(!StringUtil.isEmpty(filePath))
			{
				isSet = true;
				con.setRequestProperty("Content-Type",
						"multipart/form-data;boundary=" + boundary);
				ds = new DataOutputStream(con.getOutputStream());
				ds.writeBytes(twoHyphens + boundary + end);
				ds.writeBytes("Content-Disposition: form-data; "
						+ "name=\"file\";filename=\"" + fileName + "\"" + end);
				ds.writeBytes(end);
				fStream = new FileInputStream(new File(filePath));
				int bufferSize = 1024;
				byte[] buffer = new byte[bufferSize];
				int length = -1;
				
				while ((length = fStream.read(buffer)) != -1) {
					ds.write(buffer, 0, length);
				}
				ds.writeBytes(end);
				
				fStream.close();
			}
			
			/*
			if(params != null && params.size() > 0)
			{
				if(!isSet)
				{
					con.setRequestProperty("Content-Type",
						"multipart/form-data;boundary=" + boundary);
					isSet = true;
				}
				
				for (int i = 0; i < params.size(); i++) {
					NameValuePair pair = params.get(i);
					String value = pair.getValue();  
					String name = pair.getName();
					
		            ds.writeBytes("--" + boundary + "\r\n");  
		            ds.writeBytes("Content-Disposition: form-data; name=\"" + name  
		                    + "\"\r\n");  
		            ds.writeBytes("\r\n");  
		            ds.writeBytes(encode(value) + "\r\n");  
		            ds.writeBytes(end);
				}
			}
			*/
			
			if(ds != null)
			{
				ds.writeBytes(twoHyphens + boundary + twoHyphens + end);
				ds.writeBytes(end);
				ds.flush();
			}
			
			InputStream is = con.getInputStream();
			int ch;
			StringBuffer b = new StringBuffer();
			while ((ch = is.read()) != -1) {
				b.append((char) ch);
			}
			if(ds != null)
				ds.close();
			return b.toString();

		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
	}

}
